package weixin.processer.message;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import play.Logger;
import play.cache.Cache;
import weixin.MsgType;
import weixin.WXMessage;

/**
 * 转发消息处理接口
 * 
 * @author ultrafrog
 * @version 1.0, 2014-11-07
 * @since 1.0
 */
public abstract class WXMessageProcesser {

	private static final String CACHE	= "play_weixin_cache_processers_msg";
	
	/**
	 * 消息处理
	 * 
	 * @param wxmsg
	 * @param bkmsg
	 * @return
	 */
	public abstract Boolean process(WXMessage wxmsg, WXMessage bkmsg);
	
	/**
	 * 处理器链
	 * 
	 * @param type
	 * @return
	 */
	public static WXMessageProcesser[] get(String type) {
		Map<String, WXMessageProcesser[]> processers = processers();
		if (!processers.containsKey(type)) {
			throw new play.mvc.results.Error("type " + type + " is not defined.");
		}
		return processers.get(type);
	}
	
	/**
	 * 处理
	 * 
	 * @param wxmsg
	 * @param bkmsg
	 */
	public static void doProcess(WXMessage wxmsg, WXMessage bkmsg) {
		WXMessageProcesser[] processers = get(wxmsg.msgType);
		for (WXMessageProcesser processer: processers) {
			if (!processer.process(wxmsg, bkmsg)) {
				return;
			}
		}
	}
	
	/**
	 * 读取处理器映射表
	 * 
	 * @return
	 */
	protected static Map<String, WXMessageProcesser[]> processers() {
		Map<String, WXMessageProcesser[]> processers = Cache.get(CACHE, Map.class);
		if (processers == null) {
			try {
				processers = build();
				Cache.add(CACHE, processers);
				Logger.info("cache processer map: %s", processers);
			} catch (InstantiationException e) {
				throw new play.mvc.results.Error(e.getMessage());
			} catch (IllegalAccessException e) {
				throw new play.mvc.results.Error(e.getMessage());
			}
		}
		return processers;
	}
	
	/**
	 * 创建映射表
	 * 
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	protected static Map<String, WXMessageProcesser[]> build() throws InstantiationException, IllegalAccessException {
		// 初始化
		Map<Class<? extends WXMessageProcesser>, WXMessageProcesser> pool = new HashMap<Class<? extends WXMessageProcesser>, WXMessageProcesser>();
		Map<String, WXMessageProcesser[]> processer = new HashMap<String, WXMessageProcesser[]>();
		Field[] fields = WXMessage.Type.class.getDeclaredFields();
		
		// 遍历变量并创建映射表
		for (Field field: fields) {
			// 读取变量对应的注解
			MsgType msgType = field.getAnnotation(MsgType.class);
			
			// 若注解存在则进行处理
			if (msgType != null) {
				// 定义
				Class<? extends WXMessageProcesser>[] types = msgType.processer();
				WXMessageProcesser[] parray = new WXMessageProcesser[types.length];
				
				// 循环处理
				int i = 0;
				for (Class<? extends WXMessageProcesser> type: types) {
					if (!pool.containsKey(type)) {
						pool.put(type, type.newInstance());
					}
					parray[i++] = pool.get(type);
				}
				
				// 设置映射表
				processer.put(String.class.cast(field.get(WXMessage.Type.class)), parray);
			}
		}
		
		// 返回结果
		return processer;
	}
}
